/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.gaspar.utils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 *
 * @author chsilva
 */
public class NumeroUtil {

    private final static Logger log = LoggerFactory.getLogger(NumeroUtil.class);

    static Locale local = new Locale ("pt", "BR");
    static DecimalFormat dc = (DecimalFormat) DecimalFormat.getInstance(local);

    private static DecimalFormat decimalFormatMoeda = new DecimalFormat("0.00");

    /**
     *
     * resolve problema de ponto flutuante
     *
     * @param Valor
     *            valor formato String
     *
     * @param Decimais
     *            quantidade de casas decimais
     *
     */
    public static Double acertarDouble(Double Valor) {

        return Double.parseDouble(formatarSemMilhar(Valor, 2).replace(',', '.'));

    }


    public static Double ajustarParaMoeda(Double valor)
    {
        BigDecimal bg = new BigDecimal(decimalFormatMoeda.format(valor).replace(",", "."));
        return bg.doubleValue();
    }
    /**
     *
     * Formata valores decimais sem o ponto de milhar
     *
     * @param Valor
     *            valor decimal
     *
     * @param decimais
     *            quantidade de casas decimais
     *
     */
    public static final String formatarSemMilhar(double valor, int decimais) {

        DecimalFormat Formatador = null;

        String mascara = "################0";

        StringBuilder buf = new StringBuilder();

        for (int i = 1; i <= decimais; i++) {
            buf.append("0");
        }

        if (decimais > 0) {
            buf.insert(0, ".");
        }

        try {

            Formatador = (DecimalFormat) NumberFormat.getInstance(Locale.GERMAN);

        } catch (ClassCastException e) {

            log.error("Erro", e);
            return ("");

        }
        String padrao = buf.toString();
        Formatador.applyPattern(mascara + padrao);

        return (Formatador.format(valor));

    }

    /**
     *
     * Formata valores que contem quantidade
     *
     * @param valor
     *            Valor a ser formadado
     *
     * @param decimaisMaximos
     *            quantidade de casas decimais
     *
     */
    public static final String formatar(double valor, int decimaisMaximos,
            int decimaisMinimos) {

        DecimalFormat formatador = null;

        StringBuilder buf = new StringBuilder();

        for (int i = 1; i <= decimaisMinimos; i++) {
            buf.append("0");
        }

        for (int i = 0; i < decimaisMaximos - decimaisMinimos; i++) {
            buf.append("#");
        }

        if (decimaisMaximos > 0) {
            buf.insert(0, ".");
        }

        try {

            formatador = (DecimalFormat) NumberFormat.getInstance(Locale.GERMAN);

        } catch (ClassCastException e) {

            log.error("Erro", e);

            return ("");

        }
        
        String padrao = buf.toString();
        formatador.applyPattern("##,###,###,###,###,##0" + padrao);

        return (formatador.format(valor));

    }
    /**
     * 
     * @author Rogerio
     * @param valor
     * @param decimaisMaximos
     * @param decimaisMinimos
     * @param lado deve passar "0"para centralizar; "1" para alinhar a Esquerda e "2"para alinhar a Direita
     * @param espaco deve passar "0" zero como padrão ou um numero >= "1"
     * @return 
     */
    public static final String formatarAlinhar(double valor, int decimaisMaximos, int decimaisMinimos, int lado, int espaco) {

        DecimalFormat formatador = null;

        StringBuilder buf = new StringBuilder();
        
        for (int i = 1; i <= decimaisMinimos; i++) {
            buf.append("0");
        }

        for (int i = 0; i < decimaisMaximos - decimaisMinimos; i++) {
            buf.append("#");
        }

        if (decimaisMaximos > 0) {
            buf.insert(0, ".");
        }

        try {

            formatador = (DecimalFormat) NumberFormat.getInstance(Locale.GERMAN);

        } catch (ClassCastException e) {

            log.error("Erro", e);

            return ("");

        }
        
        switch (lado) {
            case 1:
                for (int i = 1; i <= espaco; i++) {
                buf.insert(0, " ");
                } 
            break;
                
            case 2:
                for (int i = 1; i <= espaco; i++) {
                    buf.append(" ");
                }
            break;
                
        }
        
        String padrao = buf.toString();
        formatador.applyPattern("##,###,###,###,###,##0" + padrao);

        return (formatador.format(valor));

    }

    public static final String formatar(double valor, int decimais) {
        return formatar(valor, decimais, decimais);
    }

    public static final String formatarComMilhar(double valor,
            int decimaisMaximos, int decimaisMinimos) {
        if (valor >= 1000000000d) {
            return formatar(valor / 1000000000d, decimaisMaximos, decimaisMinimos) + "Bi";
        } else if (valor >= 1000000d) {
            return formatar(valor / 1000000d, decimaisMaximos, decimaisMinimos) + "M";
        } else if (valor >= 1000d) {
            return formatar(valor / 1000d, decimaisMaximos, decimaisMinimos) + "K";
        } else {
            return formatar(valor, decimaisMaximos, decimaisMinimos);
        }
    }

    /**
     *
     * Formata valores que contem quantidade
     *
     * @param Valor
     *            Valor a ser formatado
     *
     * @param Decimais
     *            quantidade de casas decimais
     *
     */
    public static final String formatar(String Valor, int Decimais) {
        if(Valor == null)
            return null;

        return formatar(Double.valueOf(Valor.replace(',', '.')).doubleValue(), Decimais);

    }

    /**
     *
     * Formata números quaisquer com uma máscara qualquer
     *
     * @param numero
     *            Numero a ser formatado
     *
     * @param mascara
     *            Mascara que será aplicada ao n�mero
     *
     */
    public static final String formatar(double numero, String mascara) {

        DecimalFormat formatador = null;

        if(mascara == null)
            return "";

        try {

            formatador = (DecimalFormat) NumberFormat.getInstance(Locale.GERMAN);

        } catch (ClassCastException e) {
            log.error("Erro", e);
            return ("");
        }

        formatador.applyPattern(mascara);

        return (formatador.format(numero));

    }

    /**
     *
     * Formata números quaisquer com uma máscara qualquer
     *
     * @param numero
     *            Numero a ser formatado
     *
     * @param mascara
     *            Mascara que será aplicada ao número
     *
     */
    public static final String formatar(String numero, String mascara) {

        if(numero == null)
            return "";
        
        if (numero.trim().equals("")) {
            numero = "0";
        }

        try {
            return formatar(Double.parseDouble(numero), mascara);
        } catch (Exception e) {
            log.error("Erro", e);
            return "";
        }
    }

    /**
     *
     * Formata números quaisquer com uma máscara qualquer
     *
     * @param numero
     *            Numero a ser formatado
     *
     * @param mascara
     *            Mascara que ser� aplicada ao número
     *
     */
    public static final String formatar(int numero, String mascara) {
        return formatar((double) numero, mascara);
    }

    /**
     *
     * Formata n�meros quaisquer com uma m�scara qualquer
     *
     * @param numero
     *            Numero a ser formatado
     *
     * @param mascara
     *            Mascara que ser� aplicada ao n�mero
     *
     */
    public static final String formatar(long numero, String mascara) {
        return formatar((double) numero, mascara);
    }

    /**
     *
     * Formata valores em CNPJ
     *
     * @param Numero
     *            CNPJ a ser formatado
     *
     */
    public static String formatarCNPJ(String Numero) {

        if(Numero == null)
            return null;

        String AuxCNPJ = Numero.trim();

        while (AuxCNPJ.length() < 14) {
            AuxCNPJ = "0" + AuxCNPJ;
        }

        AuxCNPJ = AuxCNPJ.substring(0, 2) + "." + AuxCNPJ.substring(2, 5) + "."
                + AuxCNPJ.substring(5, 8) + "/" + AuxCNPJ.substring(8, 12) + "-"
                + AuxCNPJ.substring(12, 14);

        return AuxCNPJ;

    }

    /**
     *
     * Formata valores de CPF
     *
     * @param Numero
     *            CPF a ser formatado
     *
     */
    public static String formatarCPF(String Numero) {

        if(Numero == null)
            return null;
        
        String AuxCPF = Numero.trim();

        while (AuxCPF.length() < 11) {
            AuxCPF = "0" + AuxCPF;
        }

        AuxCPF = AuxCPF.substring(0, 3) + "." + AuxCPF.substring(3, 6) + "."
                + AuxCPF.substring(6, 9) + "-" + AuxCPF.substring(9, 11);

        return AuxCPF;

    }

    /**
     * Formata n�mero de telefone - (00)0000-0000
     *
     * @param fone
     *            N�mero de telefone a ser formatado
     * @return N�mero de telefone formatado
     */
    public static String formatarFone(String fone) {
        if(fone == null || fone.isEmpty())
            return "";
        String foneAux = fone.trim();
        return "(" + foneAux.substring(0, 2) + ")" + foneAux.substring(2, 6) + "-" + foneAux.substring(6);
    }

    /**
     * Formata n�mero do CEP - 00.000-000
     *
     * @param fone
     *            N�mero de CEP a ser formatado
     * @return N�mero do CEP formatado
     */
    public static String formatarCEP(String CEP) {
        if(CEP == null || CEP.isEmpty())
            return "";
        String CEPAux = CEP.trim();
        return CEPAux.substring(0, 2) + "." + CEPAux.substring(2, 5) + "-" + CEPAux.substring(5);
    }

    /**
     * Valida a inscricao estadual de empresas pertencentes a SUFRAMA
     * @param suframa
     * @return
     */
    public static boolean validaDigitoIESuframa(String suframa) {
        int digito = 0;
        int digitoAux = 0;
        int valorAux = 0;

        if (suframa == null || suframa.trim().length() < 8 || suframa.trim().length() > 9) {
            return false;
        }

        String campoSuframa = suframa.substring(0, suframa.length() - 1);

        try {
            if (suframa.trim().length() == 9) {
                valorAux = 
                        Integer.parseInt(campoSuframa.substring(0, 1)) * 9 +
                        Integer.parseInt(campoSuframa.substring(1, 2)) * 8 +
                        Integer.parseInt(campoSuframa.substring(2, 3)) * 7 +
                        Integer.parseInt(campoSuframa.substring(3, 4)) * 6 +
                        Integer.parseInt(campoSuframa.substring(4, 5)) * 5 +
                        Integer.parseInt(campoSuframa.substring(5, 6)) * 4 +
                        Integer.parseInt(campoSuframa.substring(6, 7)) * 3 +
                        Integer.parseInt(campoSuframa.substring(7, 8)) * 2;
            } else if (suframa.trim().length() == 8) {
                valorAux =
                        Integer.parseInt(campoSuframa.substring(0, 1)) * 8 +
                        Integer.parseInt(campoSuframa.substring(1, 2)) * 7 +
                        Integer.parseInt(campoSuframa.substring(2, 3)) * 6 +
                        Integer.parseInt(campoSuframa.substring(3, 4)) * 5 +
                        Integer.parseInt(campoSuframa.substring(4, 5)) * 4 +
                        Integer.parseInt(campoSuframa.substring(5, 6)) * 3 +
                        Integer.parseInt(campoSuframa.substring(6, 7)) * 2;
            }
            int resto = valorAux % 11;
            if (resto == 0 || resto == 1) {
                digito = 0;
            } else {
                digitoAux = 11 - resto;
                if (digitoAux > 9) {
                    String campoDigito = String.valueOf(digitoAux);
                    digito = Integer.parseInt(campoDigito.substring(0,
                            campoDigito.length() - 1));
                } else {
                    digito = digitoAux;
                }
            }
        } catch (NumberFormatException e) {
            return false;
        }
        campoSuframa += digito;
        if (campoSuframa.equals(suframa)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Valida o digito verificador da NF-e
     * @param vNum  Numero da chave de acesso da NF-e
     * @return
     */
    public static boolean verificaDigitoVerificadorChaveAcesso(String vNum) {

        if(vNum == null || vNum.length() < 44 || vNum.length() > 44 )
            return false;
        
        int vNum_Digito = Character.digit(vNum.charAt(vNum.length() - 1), 10);
        String vNum_SemDigito = vNum.substring(0, vNum.length() - 1);

        int vSomaProduto = 0;
        int vMultiplicador = 2;
        int vProduto = 0;
        for (int x = vNum_SemDigito.length() - 1; x >= 0; x--) {
            vProduto = (((int) vNum_SemDigito.charAt(x) - 48) * vMultiplicador);
            vSomaProduto += vProduto;
            if (vMultiplicador < 9) {
                vMultiplicador += 1;
            } else {
                vMultiplicador = 2;
            }
        }
        
        int vResto = (vSomaProduto - (Integer.parseInt("" + vSomaProduto / 11, 10) * 11));
        int vDigito = 11 - vResto;

        if (vDigito == 11 || vDigito == 10) {
            vDigito = 0;
        }

        return vNum_Digito == vDigito;
    }

    /**
     * Verifica o digito verificador do codigo do pais segunda tabela BACEN
     * @param campo     Codigo do pais
     * @return
     */
    public static boolean digitoVerificadorCodgPaisBACEN(String campo) {

        if (campo == null || campo.length() < 2 || campo.length() > 4) {
            return false;
        }

        if (campo.equals("1504")
            || campo.equals("1508")
            || campo.equals("4525")
            || campo.equals("3595")
            || campo.equals("4985")
            || campo.equals("6781")
            || campo.equals("7370")) {
            return true;
        }

        int digVer = 0;
        int digito1 = 0;
        int digito2 = 0;
        int digito3 = 0;

        switch (campo.length()) {
            case 2:
                digVer = Integer.parseInt(campo.substring(1, 2));
                digito1 = Integer.parseInt(campo.substring(0, 1)) * 2;
                break;
            case 3:
                digVer = Integer.parseInt(campo.substring(2, 3));
                digito1 = Integer.parseInt(campo.substring(0, 1)) * 3;
                digito2 = Integer.parseInt(campo.substring(1, 2)) * 2;
                break;
            case 4:
                digVer = Integer.parseInt(campo.substring(3, 4));
                digito1 = Integer.parseInt(campo.substring(0, 1)) * 4;
                digito2 = Integer.parseInt(campo.substring(1, 2)) * 3;
                digito3 = Integer.parseInt(campo.substring(2, 3)) * 2;
                break;
        }
//        int digVer = Integer.parseInt(campo.substring(3, 4));
//        int digito1 = Integer.parseInt(campo.substring(0, 1)) * 4;
//        int digito2 = Integer.parseInt(campo.substring(1, 2)) * 3;
//        int digito3 = Integer.parseInt(campo.substring(2, 3)) * 2;
        int somatorio = digito1 + digito2 + digito3;
        int resto = somatorio % 11;
        if (resto == 0 || resto == 1) {
            if (digVer == 0) {
                return true;
            }
            return false;
        }
        int digVerCalculado = 11 - resto;
        if (digVerCalculado == digVer) {
            return true;
        }
        return false;
    }

    /**
     * Verifica o digito verificador do codigo do municipio segundo tabela IBGE
     * @param campo     Codigo do municipio
     * @return
     */
    public static boolean digitoVerificadorCodgMunicipioIBGE(String campo) {
        
        if (campo == null || campo.length() != 7) {
            return false;
        }
        if (campo.equals("4305871")
            || campo.equals("2201919")
            || campo.equals("2202251")
            || campo.equals("2201988")
            || campo.equals("2611533")
            || campo.equals("3117836")
            || campo.equals("3152131")
            || campo.equals("5203939")
            || campo.equals("5203962")) {
            return true;
        }

        int digVer = Integer.parseInt(campo.substring(6, 7)) * 1;
        int digito1 = calculoDigito(Integer.parseInt(campo.substring(0, 1)) * 1);
        int digito2 = calculoDigito(Integer.parseInt(campo.substring(1, 2)) * 2);
        int digito3 = calculoDigito(Integer.parseInt(campo.substring(2, 3)) * 1);
        int digito4 = calculoDigito(Integer.parseInt(campo.substring(3, 4)) * 2);
        int digito5 = calculoDigito(Integer.parseInt(campo.substring(4, 5)) * 1);
        int digito6 = calculoDigito(Integer.parseInt(campo.substring(5, 6)) * 2);
        int somatorio = digito1 + digito2 + digito3 + digito4 + digito5 + digito6;
        int resto = somatorio % 10;
        if (resto == 0) {
            if (digVer == resto) {
                return true;
            }
            return false;
        }
        int digVerCalculado = 10 - resto;
        if (digVerCalculado == digVer) {
            return true;
        }
        return false;
    }

    private static int calculoDigito(int campo) {
        if (campo > 9) {
            String digitoAux = String.valueOf(campo);
            campo = (Integer.parseInt(digitoAux.substring(0, 1)) + Integer.parseInt(digitoAux.substring(1, 2)));
        }
        return campo;
    }

    /**
     *
     * @param numero
     * @return
     */
    public static Long toLong(int numero) {
        return Long.parseLong(String.valueOf(numero));
    }

    /**
     * Retorna uma m�scara (pattern) para ser aplicado ao n�mero.
     * @param maxInt    N�mero m�ximo de d�gitos da parte inteira do n�mero.
     * @param maxDec    N�mero m�ximo de d�gitos da parte decimal do n�mero.
     */
    public static String getPattern(int maxInt, int maxDec, boolean digAgrupa) {

        StringBuilder bufMaskIntNum = new StringBuilder();
        StringBuilder bufMaskDecNum = new StringBuilder();
        String newMask = "";
        int x;

        for(int i = 0; i < (maxInt - maxDec - 1); i++) {
            bufMaskIntNum.append("#");
        }

        bufMaskIntNum.append("0");

        for(int i = 0; i < maxDec; i++) {
            bufMaskDecNum.append("0");
        }

        String maskIntNum = bufMaskIntNum.toString();
        String maskDecNum = bufMaskDecNum.toString();
        for(x = maskIntNum.length(); x > 3; x = (x - 3)) {
            newMask = (digAgrupa
                ? ",".concat(maskIntNum.substring((x - 3), x)).concat(newMask)
                : maskIntNum.substring((x - 3), x).concat(newMask));
        }

        newMask = maskIntNum.substring(0, x).concat(newMask);
        return newMask.concat((maskDecNum.trim().length() > 0 ? ".".concat(maskDecNum) : maskDecNum));
    }
    
    /**
     * Preenche de zeros a esquerda de uma String com valor num�rico.
     * @param numero    String com valor num�rico.
     * @param len       Tamanho da String a ser preenchida.
     * @return          Retorna uma String preenchida com zeros a esquerda.
     */
    public static String preencheZeroEsquerda(String numero, int len) {
        String n = numero;
        n = (n == null || n.trim().length() == 0 ? "0" : n.trim());
        BigInteger x = new BigInteger(n);
        NumberFormat formatter = NumberFormat.getInstance();
        formatter.setGroupingUsed(false);
        formatter.setMinimumIntegerDigits(len);
        return formatter.format(x);
    }

    /**
     * Converte uma String com valor num�rico para BigDecimal.
     * @param numero    String com o valor n�mero a ser validada.
     * @return          Retorna um BigDecimal com o valor fornecido convertido.
     * vosouza 11-05-11 Removido opcao synchronized
     */
    public static BigDecimal getNumber(String numero, int maxDec) {

        numero = (numero == null || numero.trim().length() == 0 ? "0" : numero.trim());
        BigDecimal bd = BigDecimal.ZERO;

        NumberFormat nf = NumberFormat.getNumberInstance(local);
        try {
            bd = new BigDecimal(nf.parse(numero).toString());
        } catch (ParseException ex) {
            log.error("Erro", ex);
        }

        bd = bd.setScale(maxDec, BigDecimal.ROUND_FLOOR);

        return bd;
    }
    
    /**
    *
    */
   public static String getNumberFromBigDecimalConverter(String valor, int maxDec) {
       BigDecimal numero = null;

       if(valor == null || valor.trim().isEmpty())
           numero = BigDecimal.ZERO;
       else
           numero = new BigDecimal(valor);
       
       return formatar(numero, 10, 2, false);
   }
   
   /**
    * Executa a valida��o de uma String contendo valor num�rico, retornando seu valor
    * formatado de acordo com a m�scara.
    * @param numero    String com o valor n�mero a ser validada.
    * @param maxInt    N�mero m�ximo de d�gitos da parte inteira do n�mero.
    * @param maxDec    N�mero m�ximo de d�gitos da parte decimal do n�mero.
    * @return          Retorna uma String com valor num�rico formatada.
    */
   public static String formatar(String numero, int maxInt, int maxDec, boolean digAgrupa) {

       numero = (numero == null || numero.trim().length() == 0 ? "0" : numero.trim());

       dc.applyPattern(getPattern(maxInt, maxDec, digAgrupa));
       BigDecimal bd = BigDecimal.ZERO;
       NumberFormat nf = NumberFormat.getNumberInstance(local);

       try {
           bd = new BigDecimal(nf.parse(numero).toString());
       } catch (ParseException ex) {
           log.error("Erro", ex);
       }

       return dc.format(bd.setScale(maxDec, BigDecimal.ROUND_FLOOR));
   }
   
   /**
    * Executa a validação de uma String contendo valor numérico, retornando seu valor
    * formatado de acordo com a máscara.
    * @param numero    String com o valor n�mero a ser validada.
    * @param maxInt    N�mero m�ximo de d�gitos da parte inteira do n�mero.
    * @param maxDec    N�mero m�ximo de d�gitos da parte decimal do n�mero.
    * @return          Retorna uma String com valor num�rico formatada.
    */
   public static String formatar(BigDecimal bd, int maxInt, int maxDec, boolean digAgrupa) {
       bd = (bd == null ? BigDecimal.valueOf(0) : bd);
       dc.applyPattern(getPattern(maxInt, maxDec, digAgrupa));
       return dc.format(bd.setScale(maxDec, BigDecimal.ROUND_FLOOR));
   }
   
       /**
     * Verifica se o digito vericador do codigo de barras (cEAN / cEANTrib)
     * informado eh valido
     * @param cean (8, 12, 13, 14 posicoes)
     * @return boolean
     */
    public static boolean digitoVerificadorCean(String cean) {
        if (cean == null
                || cean.trim().length() == 0
                || cean.equals("00000000")
                || cean.equals("000000000000")
                || cean.equals("0000000000000")
                || cean.equals("00000000000000")) {
            return false;
        }
        
        int tamanho = cean.length();
        if (tamanho == 8 || tamanho >= 12 && tamanho <= 14) {
            int fator = 3;
            int soma = 0;
            int digitoInformado = Integer.parseInt(cean.substring(tamanho - 1));
            String numero = cean.substring(0, tamanho - 1);

            for (int i = tamanho - 2; i >= 0; i--) {
                if (!Character.isDigit(numero.charAt(i))){
                    return false;
                }
                soma += Integer.parseInt(String.valueOf(numero.charAt(i))) * fator;
                fator = 4 - fator;
            }

            int digitoVerificado = (1000 - soma) % 10;

            if (digitoInformado == digitoVerificado) {
                return true;
            }else {
                return false;
            }
        }

        return false;
    }
    
    /**
     * 
     * @param valor
     * @return
     */
    public static Double converterString(String valor){
	    DecimalFormatSymbols dfs = new DecimalFormatSymbols(); 
	    dfs.setDecimalSeparator(','); 
	    dfs.setGroupingSeparator('.'); 
	
	    DecimalFormat nf = (DecimalFormat)DecimalFormat.getInstance(Locale.ENGLISH); 
	    nf.setDecimalFormatSymbols(dfs);
	    Double valorDouble = null;
	    try { 
		    valorDouble = nf.parse(valor).doubleValue(); 
		} catch ( ParseException e ) { 
		    e.printStackTrace(); 
	    }
	    
	    return valorDouble;
    }
    
    /**
     * 
     * @param valor
     * @return
     */
    public static String converterNumeroString(String valor){
    	String valorStr = null;
    	if(valor.length() <= 5 ){
    		valorStr = valor.replaceAll(",", ".");
    	}else{
		    DecimalFormatSymbols dfs = new DecimalFormatSymbols(); 
		    dfs.setDecimalSeparator(','); 
		    dfs.setGroupingSeparator('.'); 
		
		    DecimalFormat nf = (DecimalFormat)DecimalFormat.getInstance(Locale.ENGLISH); 
		    nf.setDecimalFormatSymbols(dfs);
		    
		    try { 
			    valorStr = nf.parse(valor).toString(); 
			} catch ( ParseException e ) { 
			    e.printStackTrace(); 
		    }
    	}
	    
	    return valorStr;
    }
}
